/*
 * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.pig4cloud.pig.gateway.filter;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.pig4cloud.pig.gateway.config.GatewayConfigProperties;
import com.bblocks.common.Constant;
import com.bblocks.enums.SysEnum;
import com.bblocks.exception.ServiceException;
import com.bblocks.util.RSACoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.Charset;
import java.util.List;

/**
 * @author Zhao
 * @date 2023-02-28
 * 加密token解密（支持非加密token送入）
 */
@Slf4j
@RequiredArgsConstructor
public class EncryptionTokenDecoderFilter implements GlobalFilter, Ordered {

	private final GatewayConfigProperties configProperties;
	private Charset defaultCharset = Charset.forName("iso-8859-1");

	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

		String token = null;
		List<String> reqToken = exchange.getRequest().getHeaders().get(Constant.ACCESS_TOKEN_KEY);
		if (!CollectionUtil.isEmpty(reqToken)) {
			token = reqToken.get(0);
		}
		/**
		 * 为空或者长度小于64，则不解密
		 */
		if (StrUtil.isEmpty(token)){
			return chain.filter(exchange);
		}else if(StrUtil.length(token) <= 64){
			exchange.getAttributes().put(Constant.ACCESS_TOKEN_KEY, token);
			return chain.filter(exchange);
		}else if(StrUtil.isEmpty(configProperties.getTokenEncodeKey())) {
			log.warn("未配置Token解密秘钥，不予处理token！");
			exchange.getAttributes().put(Constant.ACCESS_TOKEN_KEY, token);
			return chain.filter(exchange);
		}
		try {
			byte[] privateKey = configProperties.getTokenEncodeKey().getBytes(defaultCharset);
//			token = new String(SecureUtil.rsa(privateKey, null).decrypt(Base64.decode(token),KeyType.PrivateKey),defaultCharset);
			token = new String(RSACoder.decryptByPrivateKey(token, configProperties.getTokenEncodeKey()),defaultCharset);
		} catch (Exception e) {
			throw new ServiceException(SysEnum.DECRYPT_ERROR);
		}
		exchange.getAttributes().put(Constant.ACCESS_TOKEN_KEY, token);
		return chain.filter(exchange);
	}

	public int getOrder() {
		return 0;
	}

}
